<template>
    <div class="edit-datas" ref="editChartDatasDiv">
        <section class="index_content" @mouseover="over = true;" @mouseout="over = false;">
            <div class="index_scrollTop">
                <ul :style="{ left: -currentScrollLeft + 'px', width: setScrollTopWidth(col) }">
                    <li v-for="(item, index) in col" :key="index" @click="selectCol($event, index)">
                        <span>{{ getColumnName(index) }}</span>
                    </li>
                </ul>
            </div>
            <div class="index_scrollLeft">
                <ul :style="{ top: -currentScrollTop + 'px' }">
                    <li v-for="(item, index) in row" :key="index" @click="selectRow($event, index)">
                        <span>{{ index + 1 }}</span>
                    </li>
                </ul>
            </div>
            <div class="index_scrollTable" ref="index_scrollTable">
                <span tabindex="0" class="data-grid-container">
                    <table class="data-grid index_innerTable">
                        <tbody>
                            <tr v-for="(tr, trindex) in tableData" :key="trindex">
                                <td v-for="(td, tdindex) in tr" class="cell" :class="{selected: td.selected, edited: td.edited, 'read-only': editable !== '0'}" :key="tdindex" @mousedown="cellMouseDown($event, tdindex, trindex)" @mouseup="cellMouseUp($event, tdindex, trindex)" @mouseover="cellMouseMove($event, tdindex, trindex)">
                                    <span @dblclick="cellDbClick($event, tdindex, trindex)" class="value-viewer" v-if="!td.edited">{{ td.value }}</span>
                                    <input class="data-editor" v-model="td.value" @change="editEvent" v-if="td.edited" :ref="id + '_excel_' + td.locat[0] + '_' + td.locat[1]" />
                                </td>
                            </tr>
                        </tbody>
                    </table>
                </span>
            </div>
        </section>
        <div class="index_topleft" @click="selectAll"></div>
    </div>
</template>

<script>
import util from '@/js/util/util.js';
import status from '@/js/main/status.js';
export default {
    name: 'EditChartDatas',
    props: {
        editable: {
            type: String
        },
        row: {
            type: Number,
            default: 200
        },
        col: {
            type: Number,
            default: 20
        },
        value: {
            type: Array
        },
        headList: {
            type: Array
        },
        editCallback: {
            type: Function
        }
    },
    data() {
        return {
            currentScrollLeft: 0,
            currentScrollTop: 0,
            tableData: [],
            startX: -1,
            startY: -1,
            selectMap: {},
            editItem: null,
            selectStartItem: null,
            selectEndItem: null,
            over: false,
            id: util.getID()
        };
    },
    created() {
        this.setTableData(this.value);
    },
    beforeDestroy() {
        this.$refs.index_scrollTable.removeEventListener('scroll', this.calculationScroll);
        window.removeEventListener('paste', this.pasteListenerEvent);
        window.removeEventListener('copy', this.copyListenerEvent);
        window.removeEventListener('cut', this.cutListenerEvent);
        window.removeEventListener('keyup', this.keyupListenerEvent);
        window.removeEventListener('click', this.windowFocusEvent);
    },
    mounted() {
        let _this = this;
        this.$nextTick(() => {
            _this.$refs.index_scrollTable.addEventListener('scroll', _this.calculationScroll);
            window.addEventListener('paste', _this.pasteListenerEvent);
            window.addEventListener('copy', _this.copyListenerEvent);
            window.addEventListener('cut', _this.cutListenerEvent);
            window.addEventListener('keyup', _this.keyupListenerEvent);
            window.addEventListener('click', _this.windowFocusEvent);
        });
    },
    methods: {
        editEvent() {
            if (this.editCallback) {
                this.editCallback();
            }
        },
        calculationScroll($event) {
            let scrollLeft = $event.target.scrollLeft;
            let scrollTop = $event.target.scrollTop;
            if (scrollLeft !== this.currentScrollLeft) {
                this.currentScrollLeft = $event.target.scrollLeft;
            }
            if (scrollTop !== this.currentScrollTop) {
                this.currentScrollTop = $event.target.scrollTop;
            }
        },
        selectAll() {
            this.unSelectedAll();
            for (let a = 0; a < this.row; a++) {
                for (let b = 0; b < this.col; b++) {
                    let key = a + '_' + b;
                    this.selectMap[key] = [this.tableData[a][b].locat[1], this.tableData[a][b].locat[0]];
                    this.setSelected(this.tableData[a][b], true);
                    this.setEdited(this.tableData[a][b], false);
                }
            }
            this.selectStartItem = this.tableData[0][0];
            this.selectEndItem = this.tableData[this.row - 1][this.col - 1];
        },
        selectRow(e, index) {
            if (this.editable !== '0') {
                return false;
            }
            this.unSelectedAll();
            for (let b = 0; b < this.col; b++) {
                let key = index + '_' + b;
                this.selectMap[key] = [this.tableData[index][b].locat[1], this.tableData[index][b].locat[0]];
                this.setSelected(this.tableData[index][b], true);
                this.setEdited(this.tableData[index][b], false);
            }
            this.selectStartItem = this.tableData[index][0];
            this.selectEndItem = this.tableData[index][this.col - 1];
        },
        selectCol(e, index) {
            if (this.editable === '0') {
                this.unSelectedAll();
                for (let a = 0; a < this.row; a++) {
                    let key = a + '_' + index;
                    this.selectMap[key] = [this.tableData[a][index].locat[1], this.tableData[a][index].locat[0]];
                    this.setSelected(this.tableData[a][index], true);
                    this.setEdited(this.tableData[a][index], false);
                }
                this.selectStartItem = this.tableData[0][index];
                this.selectEndItem = this.tableData[this.row - 1][index];
            }
        },
        // 双击
        cellDbClick(e, tdindex, trindex) {
            if (this.editable === '0') {
                let _this = this;
                if (e) {
                    e.stopPropagation();
                }
                if (this.editItem) {
                    this.setSelected(this.editItem, false);
                }
                this.setEdited(this.tableData[trindex][tdindex], true);
                this.editItem = this.tableData[trindex][tdindex];
                this.$nextTick(() => {
                    _this.setInputFocus(_this.getItem(_this.editItem.locat));
                });
            }
        },
        windowFocusEvent(e) {
            if (this.over == false && status.isEditTable()) {
                this.unSelectedAll();
            }
        },
        getItem(locat) {
            return this.$refs[this.id + '_excel_' + locat[0] + '_' + locat[1]];
        },
        copyListenerEvent(e) {
            if (this.selectStartItem && this.selectStartItem.edited == false && status.isEditTable()) {
                if (e.clipboardData || e.originalEvent) {
                    let clipboardData = e.clipboardData || e.originalEvent.clipboardData;
                    // 获取数据
                    let startX = Math.min(this.selectStartItem.locat[1], this.selectEndItem.locat[1]);
                    let endX = Math.max(this.selectStartItem.locat[1], this.selectEndItem.locat[1]);
                    let startY = Math.min(this.selectStartItem.locat[0], this.selectEndItem.locat[0]);
                    let endY = Math.max(this.selectStartItem.locat[0], this.selectEndItem.locat[0]);
                    let selectMap = [];
                    for (let a = startY, index = 0; a <= endY; a++, index++) {
                        selectMap[index] = [];
                        for (let b = startX; b <= endX; b++) {
                            selectMap[index].push(this.tableData[a][b].value);
                        }
                    }
                    let text = selectMap.map((item) => item.join('\t')).join('\n');
                    clipboardData.setData('text/plain', text);
                    e.preventDefault();
                }
            }
        },
        setTableData(result) {
            this.unSelectedAll();
            this.tableData = [];
            for (let trindex = 0; trindex < this.row; trindex++) {
                this.tableData.push([]);
                for (let tdindex = 0; tdindex < this.col; tdindex++) {
                    let value = '';
                    if (result && result[trindex] && result[trindex][tdindex] != null && result[trindex][tdindex] != undefined) {
                        value = result[trindex][tdindex];
                    }
                    let item = {
                        value: value,
                        selected: false,
                        edited: false,
                        locat: [trindex, tdindex]
                    };
                    this.tableData[trindex].push(item);
                }
            }
        },
        deleteSelectedItemValue() {
            for (let key in this.selectMap) {
                let index = this.selectMap[key];
                this.tableData[index[1]][index[0]].value = '';
            }
            this.editEvent();
        },
        // 剪切
        cutListenerEvent(e) {
            if (this.selectStartItem && this.selectStartItem.edited == false && status.isEditTable()) {
                this.copyListenerEvent(e);
                this.deleteSelectedItemValue();
                this.editEvent();
            }
        },
        // 粘贴
        pasteListenerEvent(e) {
            if (this.selectStartItem && this.selectStartItem.edited == false && status.isEditTable()) {
                let text = (e.clipboardData || window.clipboardData).getData('text');
                let row = text.split(/[(\r\n)\r\n]+/);
                let grid = [];
                for (let a = 0; a < row.length; a++) {
                    if (row[a] != '') {
                        grid.push(row[a].split(/[(\t)\t]+/));
                    }
                }
                let start = this.selectStartItem.locat;
                let end = this.selectEndItem.locat;
                for (let trindex = start[0]; trindex <= (this.selectStartItem != this.selectEndItem ? end[0] : this.row - 1); trindex++) {
                    for (let tdindex = start[1]; tdindex <= (this.selectStartItem != this.selectEndItem ? end[1] : this.col - 1); tdindex++) {
                        if (grid[trindex - start[0]] && grid[trindex - start[0]][tdindex - start[1]] != null && grid[trindex - start[0]][tdindex - start[1]] != undefined) {
                            this.tableData[trindex][tdindex].value = grid[trindex - start[0]][tdindex - start[1]];
                        }
                    }
                }
                e.preventDefault();
                this.editEvent();
            }
        },
        keyupListenerEvent(e) {
            if (this.selectStartItem && this.selectStartItem.edited == false && status.isEditTable()) {
                if (e.ctrlKey && e.keyCode == 67) {
                    // 复制
                } else if (e.ctrlKey && e.keyCode == 88) {
                    // 剪切
                } else if (e.ctrlKey && e.keyCode == 86) {
                    // 粘贴
                } else if (e.keyCode == 46) {
                    // 删除
                    this.deleteSelectedItemValue();
                } else if ((48 <= e.keyCode && e.keyCode <= 57) || (65 <= e.keyCode && e.keyCode <= 90) || (96 <= e.keyCode && e.keyCode <= 111) || (187 <= e.keyCode && e.keyCode <= 192) || (219 <= e.keyCode && e.keyCode <= 222)) {
                    let x = this.selectStartItem.locat[0];
                    let y = this.selectStartItem.locat[1];
                    this.tableData[x][y].value = '';
                    this.cellDbClick(null, y, x);
                    this.tableData[x][y].value = e.key;
                    this.editEvent();
                }
            }
        },
        unSelectedAll() {
            for (let key in this.selectMap) {
                let index = this.selectMap[key];
                this.setSelected(this.tableData[index[1]][index[0]], false);
            }
            this.selectMap = {};
            this.selectStartItem = null;
            this.selectEndItem = null;
        },
        setSelected(cell, state) {
            cell.selected = state;
            if (state == false) {
                cell.edited = false;
            }
        },
        setEdited(cell, state) {
            cell.edited = state;
            if (state == true) {
                cell.selected = true;
            }
        },
        setInputFocus(cell) {
            cell[0].focus();
        },
        cellMouseDown(e, tdindex, trindex) {
            if (this.editable === '0') {
                this.startX = tdindex;
                this.startY = trindex;
            }
        },
        cellMouseMove(e, tdindex, trindex) {
            if (this.editable === '0') {
                if (this.startX >= 0 && this.startY >= 0) {
                    let startX = Math.min(this.startX, tdindex);
                    let endX = Math.max(this.startX, tdindex);
                    let startY = Math.min(this.startY, trindex);
                    let endY = Math.max(this.startY, trindex);
                    let selectMap = {};
                    for (let a = startX; a <= endX; a++) {
                        for (let b = startY; b <= endY; b++) {
                            let key = a + '_' + b;
                            selectMap[key] = [a, b];
                            if (this.selectMap[key]) {
                                delete this.selectMap[key];
                            }
                            this.setSelected(this.tableData[b][a], true);
                            this.setEdited(this.tableData[b][a], false);
                        }
                    }
                    for (let key in this.selectMap) {
                        let index = this.selectMap[key];
                        this.setSelected(this.tableData[index[1]][index[0]], false);
                    }
                    this.selectMap = selectMap;
                }
            }
        },
        cellMouseUp(e, tdindex, trindex) {
            if (this.editable === '0') {
                e.stopPropagation();
                if (tdindex == this.startX && trindex == this.startY) {
                    for (let key in this.selectMap) {
                        let index = this.selectMap[key];
                        if (index[0] != this.startX || index[1] != this.startY) {
                            this.setSelected(this.tableData[index[1]][index[0]], false);
                        }
                    }
                }
                this.selectStartItem = this.tableData[Math.min(this.startY, trindex)][Math.min(this.startX, tdindex)];
                this.selectEndItem = this.tableData[Math.max(this.startY, trindex)][Math.max(this.startX, tdindex)];
                this.startX = -1;
                this.startY = -1;
                this.setSelected(this.tableData[trindex][tdindex], true);
                if (this.editItem && this.editItem != this.tableData[trindex][tdindex]) {
                    this.setEdited(this.editItem, false);
                    this.editItem = null;
                }
                this.selectMap[tdindex + '_' + trindex] = [tdindex, trindex];
            }
        },
        getTableData() {
            let arr = [];
            for (let trindex = 0; trindex < this.row; trindex++) {
                let row = [];
                for (let tdindex = 0; tdindex < this.col; tdindex++) {
                    let value = this.tableData[trindex][tdindex].value;
                    if (value !== '' && value !== null && value !== undefined) {
                        row.push(value);
                    } else {
                        break;
                    }
                }
                if (row.length) {
                    arr.push(row);
                } else {
                    break;
                }
            }
            return arr;
        },
        setScrollTopWidth(col) {
            return `calc(120px * ${col} + 2px * ${col})`;
        },
        getColumnName(n) {
            n++;
            if (n < 1) {
                n = 1;
            }
            let name = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
            let s = '';
            while (n > 0) {
                let m = n % name.length;
                if (m == 0) m = name.length;
                s = name[m - 1] + s;
                n = (n - m) / name.length;
            }
            return s;
        }
    }
};
</script>

<style lang="scss" scoped>
.edit-datas {
    font-size: 12px;
    color: #90929b;
    position: relative;
    width: 100%;
    height: 100%;
    .index_topleft {
        width: 18px;
        height: 18px;
        line-height: 18px;
        text-align: center;
        background-color: #383939;
        position: absolute;
        top: 0;
        left: 0;
        z-index: 66;
        cursor: pointer;
    }
    .index_content {
        width: 2458px; // 236
        // width: 100%; // 236
        height: 100%; // calc(232px + 18px)
        overflow: hidden;
        background-color: #222222;
        position: relative;
    }
    .index_scrollTop {
        height: 18px;
        width: calc(2458px - 18px); // 218 1238px
        // width: 100%; // 218
        -webkit-user-select: none;
        -ms-user-select: none;
        user-select: none;
        margin-left: 18px;
        overflow: hidden;
        background-color: inherit;
        position: absolute;
        z-index: 44;
        > ul {
            height: inherit;
            position: relative;
            text-align: center;
            cursor: pointer;
            margin: 0;
        }
        > ul li {
            display: block;
            box-sizing: content-box;
            height: 18px;
            width: 120px; // 84px
            border: 1px solid #383939;
            margin: 0 -1px 0 0;
            border-bottom: 0;
            float: left;
            position: relative;
        }
        > ul li span {
            display: block;
            -webkit-transform: scale(0.8);
            transform: scale(0.8);
            margin-left: -2px;
        }
    }
    .index_scrollLeft {
        width: 18px;
        height: calc(100% - 18px); // 232px
        background-color: inherit;
        overflow: hidden;
        -webkit-user-select: none;
        -ms-user-select: none;
        user-select: none;
        float: left;
        position: absolute;
        z-index: 33;
        top: 18px;
        ul {
            position: relative;
            width: 100%;
            background-color: #222222;
            text-align: center;
            letter-spacing: -1px;
            margin: 0;
            cursor: pointer;
        }
        ul li {
            height: 26px;
            line-height: 26px;
            border: 1px solid #383939;
            margin: 0 -1px -1px 0;
            position: relative;
        }
        ul li span {
            display: block;
            -webkit-transform: scale(0.8);
            transform: scale(0.8);
            margin-left: -2px;
        }
    }
    .index_scrollTable {
        width: calc(2440px - 18px); // 218 1238px 2440
        height: calc(100% - 18px); // 232px
        // overflow: scroll;
        overflow: hidden;
        overflow-y: auto;
        position: absolute;
        left: 18px;
        top: 18px;
        z-index: 11;
    }
    .index_innerTable {
        min-width: 100%;
        background-color: #171717;
        color: #ffffffde;
    }
    .index_thead {
        background-color: #161824;
    }
    .index_scrollTable .data-grid-container .data-grid .cell {
        width: 120px; // 84px
    }
    .data-grid-container .data-grid .cell {
        width: 100%;
        user-select: none;
        -moz-user-select: none;
        -webkit-user-select: none;
        -ms-user-select: none;
        cursor: cell;
        background-color: unset;
        transition: background-color 500ms ease;
        vertical-align: middle;
        text-align: right;
        border: 1px solid #383939;
        padding: 0;
        box-sizing: border-box;
    }
    .data-grid-container .data-grid {
        table-layout: auto;
        border-collapse: collapse;
        position: relative;
    }
    .data-grid-container .data-grid .cell .value-viewer,
    .data-grid-container .data-grid .cell .data-editor {
        display: block;
        box-sizing: border-box;
        height: 24px;
        line-height: 24px;
        width: inherit;
        text-align: left;
        padding: 0 2px;
        overflow: hidden;
        white-space: nowrap;
        color: #ffffffde;
    }
    .data-grid-container .data-grid .cell > input {
        outline: none !important;
        border: 0;
        text-align: right;
        width: 100%;
        height: inherit;
        background: none;
        display: block;
    }
    .data-grid-container .data-grid .cell.selected {
        border: 1px double #2643a1;
        transition: none;
        box-shadow: inset 0 -100px 0 rgb(47 84 201 / 30%);
    }
    .data-grid-container .data-grid .cell.selected.edited {
        border-color: #2f54c9;
        box-shadow: none;
    }
    .data-grid-container .data-grid .cell.read-only {
        color: #999;
        text-align: center;
    }
}
</style>